import {
  computed,
  createVNode,
  defineComponent,
  onMounted,
  reactive,
  render,
  ref,
  onBeforeUnmount,
  provide,
  inject,
} from "vue";
const dropDownComponent = defineComponent({
  props: { option: Object },
  setup(props, ctx) {
    const state = reactive({
      option: props.option,
      isShow: false,
      top: 0,
      left: 0,
    });
    ctx.expose({
      showDropDown(option) {
        state.option = option;
        state.isShow = true;
        const { left, top, height } = option.el.getBoundingClientRect();
        state.top = top + height;
        state.left = left + height;
      },
    });
    provide("hide", () => {
      state.isShow = false;
    });
    const classes = computed(() => [
      "dropdown",
      { "dropdown-isshow": state.isShow },
    ]);
    const styles = computed(() => ({
      top: state.top + "px",
      left: state.left + "px",
    }));
    const el = ref(null);
    const onMouseDownDocument = (e) => {
      if (!el.value.contains(e.target)) {
        state.isShow = false;
      }
    };
    onMounted(() => {
      // 事件传递的行为是先捕获再冒泡
      document.body.addEventListener("mousedown", onMouseDownDocument, true);
    });
    onBeforeUnmount(() => {
      document.body.removeEventListener("mousedown", onMouseDownDocument);
    });
    return () => (
      <div class={classes.value} style={styles.value} ref={el}>
        {state.option.content()}
      </div>
    );
  },
});

export const dropDownItem = defineComponent({
  props: {
    label: String,
    icon: String,
  },
  setup(props, ctx) {
    const hide = inject("hide");
    const { label, icon } = props;
    return () => {
      return (
        <div class="dropdown-item" onClick={hide}>
          <span>{label}</span>
        </div>
      );
    };
  },
});

let vNode;
export function $dropDown(option) {
  if (!vNode) {
    // 创建 el 元素
    const el = document.createElement("div");
    // 将组件渲染成虚拟节点
    vNode = createVNode(dropDownComponent, { option });
    // 将组件渲染到 el 元素上，然后将 el 渲染到页面中
    document.body.appendChild((render(vNode, el), el));
  }
  const { showDropDown } = vNode.component.exposed;
  showDropDown(option);
}
